/*
 * Copyright (C) 2010 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
#include <pthread.h>
#include <cutils/memory.h>

#include <utils/Log.h>

//#include <system/window.h>

#include <binder/IPCThreadState.h>
#include <binder/ProcessState.h>
#include <binder/IServiceManager.h>

#include <gui/Surface.h>
#include <gui/SurfaceComposerClient.h>
 #include <gui/ISurfaceComposer.h>

#define CHECK_RET() do{ if(ret) \
 printf("error:\t\tline:%d ret:%d\n", __LINE__, ret); \
 else \
    printf("OK:\t\tline:%d ret:%d\n", __LINE__, ret); \
} while(0)

using namespace android;

static sp<SurfaceControl> mSC;
static int slot,width=1920,height=1080;
static sp<GraphicBuffer> buf;
static sp<ISurfaceTexture> mIST;
static sp<SurfaceTextureClient> mSTC;
static sp<SurfaceComposerClient> mSCC;
static sp<ANativeWindow> mANW;
static sp<Fence> fence;
static void* img = NULL;
static  ANativeWindowBuffer* buffer_droped;
static  ANativeWindowBuffer* buffer = NULL ;
static sp<GraphicBuffer> anb;
static int fenceFD = -1;

void set_one_buff(){
 int err = mIST->setBufferCount(2);
 printf("setBufferCount 2:%d\n", err);
 err = mANW->dequeueBuffer(mANW.get(), &buffer_droped,  &fenceFD);
 printf("set_one_buff: dequeueBuffer ret: %d\n", err);    
}

void* app_fix_buff_lock(){
    int ret = 0;
    if(buffer == NULL){
        ret  = mANW->dequeueBuffer(mANW.get(), &buffer,  &fenceFD);
        anb = new GraphicBuffer(buffer, true);
        anb->lock(GRALLOC_USAGE_SW_WRITE_OFTEN|GRALLOC_USAGE_HW_FB, (void**)(&img));
    }else{
        ret  = mANW->dequeueBuffer(mANW.get(), &buffer,  &fenceFD);
        anb->lock(GRALLOC_USAGE_SW_WRITE_OFTEN|GRALLOC_USAGE_HW_FB, (void**)(&img));
    }

    printf("app_fix_buff_lock: dequeueBuffer ret:%d\n",  ret);
    printf("buffer address:%p\n", buffer);
    printf("img address:%p\n", img);
}

void app_fix_buff_unlock_and_post(){
    anb->unlock();
    int ret = mANW->queueBuffer(mANW.get(), buffer, -1);
    printf("queue buffer:%p ret:%d\n",  buffer, ret);
}


void sys_app_updateFrame(){
   anb->lock(GRALLOC_USAGE_SW_WRITE_OFTEN|GRALLOC_USAGE_HW_FB, (void**)(&img));
   anb->unlock();
}

static void start_test(void* buf);
int main(int argc, char** argv)
{
    printf("entry main\n");

    mSCC = new SurfaceComposerClient();
    mSC = mSCC->createSurface(
        String8("surface"), width, height, PIXEL_FORMAT_RGBA_8888, 0);
    SurfaceComposerClient::openGlobalTransaction();
    mSC->setLayer(27000);
    SurfaceComposerClient::closeGlobalTransaction();
    mIST =  mSC->getSurface()->getSurfaceTexture();
    mANW =  mSC->getSurface().get();

    set_one_buff();

    app_fix_buff_lock();
    memset(img, 128, width*height*4);
    app_fix_buff_unlock_and_post();

    start_test(img);

    while(1){
        sys_app_updateFrame();
        usleep(90000);
    }

     printf("test complete. CTRL+C to finish.\n");

    sleep(50);

    return 0;
}

static void* pixels;

static pthread_t thread_test;
static void *test_fun(void* arg){
    fprintf(stdout, "Test thread run\n");
    fflush(stdout);

   uint32_t colors[] = { 0xEF00FF00, 0xEFFF0000, 0xEF0000FF};
   uint32_t* pColor = (uint32_t*)pixels;
    for(int i=0;i <2048; i++){ 

        for(int j=0;j<height; j++){
            for(int k=0;k<width; k++){
                pColor[width*j+k] = colors[i%3];
            }
        }

        usleep(100000);
    }

    fprintf(stdout, "Test thread end.\n");
}

static void start_test(void* buf){
    fprintf(stdout, "Start Test thread, bufffer:%p\n", buf);
    pixels = buf;
    pthread_create(&thread_test, NULL, &test_fun, NULL);
}
